package org.vison.wonfu.framework.soa.governance;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.hc.client5.http.async.methods.SimpleHttpRequest;
import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder;
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
import org.apache.hc.core5.concurrent.FutureCallback;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.io.CloseMode;
import org.apache.hc.core5.reactor.IOReactorStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.vison.wonfu.framework.commons.Constants;
import org.vison.wonfu.framework.commons.utils.AppUtils;
import org.vison.wonfu.framework.config.utils.MultiLevelConfigProvider;
import org.vison.wonfu.framework.soa.SoaConstants;
import org.vison.wonfu.framework.soa.context.SoaApplicationContext;

import javax.annotation.Resource;
import java.io.IOException;

@ConditionalOnProperty(name = SoaConstants.GOVERNANCE_REPORT_ENABLED, havingValue = "true", matchIfMissing = true)
public class GovernanceReporter implements CommandLineRunner {

    private static final Logger logger = LoggerFactory.getLogger(GovernanceReporter.class);

    @Resource(name = Constants.GOVERNANCE_BEAN)
    private MultiLevelConfigProvider multiLevelConfigProvider;

    @Override
    public void run(String... args) throws Exception {
        // report meta data
        ObjectMapper objectMapper = SoaApplicationContext.getDefaultObjectMapper();
        MetaReq metaReq = new MetaReq();
        metaReq.setAppId(AppUtils.getAppId());
        metaReq.setGovernanceConfig(new GovernanceConfig());
        metaReq.setConsumerMetas(MetaData.getConsumerMetas());
        metaReq.setProviderMetas(MetaData.getProviderMetas());
        String consumerBody = objectMapper.writeValueAsString(metaReq);
        httpPost(consumerBody);
    }

    private void httpPost(String content) throws IOException {
        String governanceHost = multiLevelConfigProvider.getString(Constants.ORBIT_DOMAIN);
        String governanceUrl = governanceHost + "/soa/meta";
        CloseableHttpAsyncClient httpClient = HttpAsyncClients.createDefault();
        httpClient.start();
        SimpleHttpRequest request = SimpleRequestBuilder.post(governanceUrl).setBody(content,
                ContentType.APPLICATION_JSON).build();
        httpClient.execute(request, new FutureCallback<SimpleHttpResponse>() {
            @Override
            public void completed(SimpleHttpResponse response) {
                // 异步回调处理
                if(response.getCode() == 200){
                    logger.info("report soa meta data to: {}  completed", governanceUrl);
                }else{
                    logger.error("report soa meta data failed to {} with code: {}", governanceUrl, response.getCode());
                }
                closeHttpClient(httpClient);
            }

            @Override
            public void failed(Exception ex) {
                logger.error("report soa meta data failed to {}", governanceUrl, ex);
                closeHttpClient(httpClient);
            }

            @Override
            public void cancelled() {
                // 取消处理
                logger.warn("report soa meta data cancelled");
                closeHttpClient(httpClient);
            }
        });
        // 移除这里的关闭操作，防止I/O reactor过早关闭
        // httpClient.close(CloseMode.GRACEFUL);
    }

    // 添加一个辅助方法来关闭HTTP客户端
    private void closeHttpClient(CloseableHttpAsyncClient httpClient) {
        if (httpClient != null && httpClient.getStatus() != IOReactorStatus.ACTIVE) {
            httpClient.close(CloseMode.GRACEFUL);
        }
    }
}